package controller;

import helper.Balance;
import helper.Calendr;
import helper.Formatter;
import helper.UserSession;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.mybeans.dao.DAOException;

import databeans.Customer;
import databeans.Employee;
import databeans.Fund;
//import databeans.FundHistory;
import databeans.Transaction;
import model.CustomerDAO;
import model.FundDAO;
import model.Model;
import model.TransactionDAO;

public class CustomerBuyFundAction extends Action{
    private FundDAO fundDAO;
    private TransactionDAO transactionDAO;
    private CustomerDAO customerDAO;
    
    public CustomerBuyFundAction(Model model) {
        fundDAO = model.getFundDAO();
        transactionDAO = model.getTransactionDAO();
        customerDAO = model.getCustomerDAO();
    }
    
    public String getName() {
        return "customerBuyFund.do";
    }
    

    public String perform(HttpServletRequest request) {
        //ATTENTION
        // define target page
    	String loginPage = "customer/customer-login.jsp";
        String originPage = "customer/buy-funds.jsp";
        String successPage = originPage;
        //String successPage = "customer/view-transaction-history.jsp"; 
        
        //set the employee
        Customer customer = null;
        Employee employee = null;
        Fund fund = null;
        //FundHistory fundHistory = null;

        //errors and messages will be stored here
        //resetting those containers
        List<String> errors = new ArrayList<String>();
        List<String> messages = new ArrayList<String>();
   
        //define the error and message
        request.setAttribute("errors", errors);
        request.setAttribute("messages", messages);
        request.setAttribute("page", "buy-fund");
        
        //check if customer has actually logged in
        customer = UserSession.getLoggedInCustomer(request);
        if (customer == null) {
            errors.add("You need to log in");
            return loginPage;
        }
        
        //feed customer ID
        String customerID = Integer.toString(customer.getCustomerID());
        long customerAvailableCash = 0;
        //DecimalFormat twoDForm = new DecimalFormat("#.##");
        try {
        	customerAvailableCash = Balance.getCustomerAvailableCash(customer);            
        } catch (DAOException e1) {
            errors.add("Customer available balance could not be resolved");
            return originPage;
        }

        request.setAttribute("cashBalance", Double.valueOf(Formatter.prepCashToView(customerAvailableCash)));
        
        if(customerAvailableCash<=0)
        {
        	errors.add("You do not have sufficient Cash Balance to purchase Funds. Please try again later.");
            return originPage;
        }
        
        //get all the parameter from the form
        String requestType = request.getParameter("Submit");    
        String fundID = request.getParameter("txtFundID");
        String submissionDate = Calendr.getTodayDateString(); //request.getParameter("txtSubmissionDate");
        String amount = request.getParameter("txtAmount");

        //reload the form field
        request.setAttribute("txtFundID", fundID);
        request.setAttribute("txtSubmissionDate", submissionDate);
        request.setAttribute("txtAmount", amount);
        
        //Load all the fund
        try {
            Fund [] fundArray = fundDAO.getFunds();
            request.setAttribute("funds", fundArray);
            
            if (fundArray == null){
                messages.add("Currently there is no Fund you can select");
            }
        } catch (DAOException e2) {
            errors.add("funds could not be retrieved");
            errors.add("msg: "+ e2.getMessage());
            return originPage;
        }

        //check if employee has been logged in
        //request.getSession() will return the current session and if one does not exist, a new session will be cretaed.
        //request.getSession(true) will return the current session if one exists, if one doesn't exits a new one will be created.
        //So there is actually no difference between the two methods HOWEVER, if you use request.getSession(false), it will return the current session if one exists and if one DOES NOT exist a new one will NOT be cretaed.
        employee = UserSession.getLoggedInEmployee(request);
        if (employee != null) {
            UserSession.removeEmployeeFromSession(request);
            errors.add("This section is closed for employee");
            return loginPage ;
        }
        
        //check if customer has actually logged in
        customer = UserSession.getLoggedInCustomer(request);
        if (customer == null) {
            errors.add("You need to log in");
            return loginPage;
        }
        
        //feed customer ID
        customerID = Integer.toString(customer.getCustomerID());
        
        //validate if user has necessary qualification
        //check the session


        // check for get or post request
        //if there is no parameter get passed, return to origin page
        if (requestType == null) {
            messages.add("Choose the fund and amount of shares to buy from that fund.");
            return originPage;     
        }
        
        //validate the input
        if (fundID.trim().equals("")) {
            messages.add("Please Choose a Fund from the List");
            errors.add("Fund ID could not be retrieved");
            return originPage;
        }
        
        /*
        if (transactionType.trim().equals("")) {
            messages.add("Transaction Type must be provided");
            errors.add("Current Transaction Type field is still empty");
            return originPage;
        }*/
        /*
        if (transactionType.trim().equals(Transaction.SELL_ORDER) || 
                transactionType.trim().equals(Transaction.BUY_ORDER) || 
                transactionType.trim().equals(Transaction.EXCHANGE_BUY_ORDER) ||
                transactionType.trim().equals(Transaction.EXCHANGE_SELL_ORDER) 
                ){
            //nothing here
        } else {
            messages.add("Transaction types are predetermined");
            errors.add("Current transaction type does not fit preexisting types");
            return originPage;
        }*/
        
        //assume exchange has not been specified
        /*
        if (shares.trim().equals("") && amount.trim().equals("")) {
            messages.add("Either shares and amount must be specified but not both");
            errors.add("You have specified both amount and shares");
            return originPage;
        }
        */
        
        if (amount.trim().equals("")) {
            messages.add("Please enter the dollar amount of shares you want to purchase");
            errors.add("Purchase amount has not been specified");
            return originPage;
        }

        //check if customerid is valid
        try{
            customer = customerDAO.lookup(Integer.parseInt(customerID));
        } catch (NumberFormatException e1) {
            errors.add("Customer associated could not be retrieved - Customer ID could not be recognized");
            return loginPage;
        } catch (DAOException efundtry) {
            errors.add("Customer associated could not be retrieved");
            return loginPage;
        }

        //check if fundid is valid
        try {
            fund = fundDAO.lookup(Integer.parseInt(fundID));
        } catch (NumberFormatException e1) {
            errors.add("Fund associated could not be retrieved - FundID could not be recognized");
            return originPage;
        } catch (DAOException efundtry) {
            errors.add("Fund associated could not be retrieved");
            return originPage;
        }
        

        //check if double value inputted is A double
        if (!Formatter.isDouble(amount)){
            //messages.add("You must input a number in amount field");
            errors.add("Invalid input in Amount field. Please check.");
            return originPage;
        }
        
        //check if double has 2 decimal place
        if(Formatter.numberOfDecimal(amount)>2) {
            messages.add("CFA only tracks amount up to two decimal place. Please reenter the amount");
            errors.add("Accuracy could not be captured");
            return originPage;
        }
        
        //check if amount entered is < (Customer.cash - (Sigma)BuyOrder.amount)

        if (customerAvailableCash >= Formatter.prepCashFromView(Double.parseDouble(amount))) {
            //messages.add("Buy Order is submitted as you have enough balance to cover the purchase ");
        } else {
            //messages.add("You do not have enough cash to cover the order. You have $" + customerAvailableCash + "available for trading");
            errors.add("Not enough cash");
            return originPage;
        }
        
        //ensure no negative number
        if ( Double.parseDouble(amount) <= 0.00 ){
            //messages.add("The amount should not be negative");
            errors.add("Invalid input for Number of Shares to purchase. Please check.");
            return originPage;
        }
        
    
        // at this stage, all input validation should have been done
        try {
  


            Transaction tempTrans = new Transaction();
            tempTrans.setFundID(Integer.parseInt(fundID));
            tempTrans.setCustomerID(Integer.parseInt(customerID));
            tempTrans.setSubmissionDate(Calendr.getTodaysDate());
            tempTrans.setTransactionType(Transaction.BUY_ORDER);
            //tempTrans.setShares(Double.parseDouble(shares));
            tempTrans.setAmount(Formatter.prepCashFromView(amount));

            //push those transaction object into database
            tempTrans = transactionDAO.create(tempTrans);
            

            // Attach (this copy of) the logged in employee bean to the session
            HttpSession session = request.getSession(true); 
            session.setAttribute("customer", customer );

            //email
            //TODO activate this later
            //Postman.sendBuyOrderConfirmation(tempTrans, fund, customer);
            

            //refresh customer available cash
            try {
                customerAvailableCash = Balance.getCustomerAvailableCash(customer);         
                //customerAvailableCash = Double.valueOf(twoDForm.format(Balance.getCustomerAvailableCash(customer)));            
            } catch (DAOException e1) {
                errors.add("Customer available balance could not be resolved");
                return originPage;
            }

            request.setAttribute("cashBalance", Double.parseDouble(Formatter.prepCashToView(customerAvailableCash)));
            request.setAttribute("txtAmount", "");
            messages.add("Your purchase order has been succesfully placed for amount <b>$" + Formatter.prepCashToView(tempTrans.getAmount()) + "</b> with the <b>" + fund.getName() +"</b>");
            return successPage;

        } catch (Exception e) {
            errors.add("Unable to place Buy Order! Please try again later " + e.getMessage());
            System.out.println(e.getMessage());
            return originPage;
        }

    }
}